#include "platform.h"

#include "utility.h"

#include "usart.h"
#include "string.h"
#include "data.h"
#include "mod_gprs.h"
#include "mod_eth.h"
#include "sal_module_wrapper.h"

#include <math.h>
#include <stdlib.h>
#include <Net_Config.h>

struct SocketApi g_socket_api ={0};
    
uint64_t os_pal_time(void){
    return 0;
}

/* RL-TCPnet API的返回值 */
const char * ReVal_Table[]= 
{
	" 0: SCK_SUCCESS       Success                             ",
	"-1: SCK_ERROR         General Error                       ",
	"-2: SCK_EINVALID      Invalid socket descriptor           ",
	"-3: SCK_EINVALIDPARA  Invalid parameter                   ",
	"-4: SCK_EWOULDBLOCK   It would have blocked.              ",
	"-5: SCK_EMEMNOTAVAIL  Not enough memory in memory pool    ",
	"-6: SCK_ECLOSED       Connection is closed or aborted     ",
	"-7: SCK_ELOCKED       Socket is locked in RTX environment ",
	"-8: SCK_ETIMEOUT      Socket, Host Resolver timeout       ",
	"-9: SCK_EINPROGRESS   Host Name resolving in progress     ",
	"-10: SCK_ENONAME      Host Name not existing              ",
};
//socket init
pal_socket_t pal_line_create_socket(const char_t *addr, int32_t port){
	  int sock;
    unsigned long sck_mode;
	  int ret;
	
	  SOCKADDR_IN sock_addr;
    
	  sock = socket(AF_INET,SOCK_STREAM,0);
	  if(sock < 0) {
		  closesocket(sock);
		  return sock;
	  }
      
    sck_mode = 1;
    //ret = ioctlsocket (sock, FIONBIO, &sck_mode);
    ret = ioctlsocket (sock, FIO_KEEP_ALIVE, &sck_mode);
    if (ret != SCK_SUCCESS){
        closesocket(sock);     
			  return ret;
    }
    int32_t addr_val[4]={0};
    sscanf(addr, "%d.%d.%d.%d", &addr_val[0], &addr_val[1], &addr_val[2], &addr_val[3]);
	  sock_addr.sin_family = PF_INET;	
	  sock_addr.sin_port = htons(port);
	  sock_addr.sin_addr.s_b1 = addr_val[0];
    sock_addr.sin_addr.s_b2 = addr_val[1];
    sock_addr.sin_addr.s_b3 = addr_val[2];
    sock_addr.sin_addr.s_b4 = addr_val[3];
    
  	ret = connect(sock,(SOCKADDR *)&sock_addr,sizeof(sock_addr));
    printf("server connect:%s\r\n", ReVal_Table[abs(ret)]);
	  if(ret != SCK_SUCCESS){
		 closesocket(sock);
		 return ret;
	  }
  	return sock;
}

pal_socket_t pal_gprs_create_socket(const char_t *addr, int32_t port){
      return gprs_connect();
}

pal_socket_t pal_w4g_create_socket(const char_t *addr, int32_t port){
     //return w4g_connect();
    char_t port_str[10]={0};
    sprintf(port_str, "%d", port);
    return tos_sal_module_connect(addr, port_str, TOS_SAL_PROTO_TCP);
}

//send msg
int32_t pal_line_sendall(pal_socket_t s, const void* buf, size_t len, int flags){
	int send_len = -1;
    //printf("pal send len:%d\r\n", len);
	send_len = send(s,buf,len,MSG_DONTWAIT);
	return send_len;
}

int32_t pal_gprs_sendall(pal_socket_t s, const void* buf, size_t len, int flags){
    return gprs_send_msg(buf, len);
    
}

int32_t pal_w4g_sendall(pal_socket_t s, const void* buf, size_t len, int flags){
    //return w4g_send_msg(buf, len);
    return tos_sal_module_send(s, buf, len);
}

//recv msg
int32_t pal_line_recvall(pal_socket_t s, void* buf, size_t bufsz, int flags){
	int32_t len;
    //printf("pal recv all size:%d\r\n", bufsz);
	len = recv(s,buf,bufsz, MSG_DONTWAIT);
	if(len <= 0){
        //printf("recv err:%s\r\n", ReVal_Table[abs(len)]);
        if((len == SCK_EINVALID) || (len == SCK_ECLOSED) || (len == SCK_EWOULDBLOCK))
        {
            return 0;	
        }
    }
	return len;
}

int32_t pal_gprs_recvall(pal_socket_t s, void* buf, size_t bufsz, int flags){
    return gprs_read_msg(buf, bufsz);
}

int32_t pal_w4g_recvall(pal_socket_t s, void* buf, size_t bufsz, int flags){
    //return w4g_read_msg(buf, bufsz);
    return tos_sal_module_recv_timeout(s, buf, bufsz, 100);
}
//close socket
void pal_line_close_socket(pal_socket_t s){
    closesocket(s);
}

void pal_gprs_close_socket(pal_socket_t s){

}
void pal_w4g_close_socket(pal_socket_t s){
    tos_sal_module_close(s);
}
int32_t pal_pthread_create(char_t* threadName ,os_pthread_t *thread ,void (*start_routine)(void *arg) ,void *para ,int32_t prio ,int32_t stack_size ) 
{  
	BaseType_t xReturned = pdFAIL;
	
	if(NULL != thread && NULL != start_routine)
	{
    	xReturned = xTaskCreate(
    		start_routine,       /* Function that implements the task. */
    		threadName,          /* Text name for the task. */
    		stack_size,          /* Stack size in words, not bytes. */
    		para,                 /* Parameter passed into the task. */
    		(uint8_t)prio,       /* Priority at which the task is created. */
    		thread);             /* Used to pass out the created task's handle. */
    	
    	if (pdPASS == xReturned) 
    		return 0;
	}	
	
	return -1;
}

int32_t pal_mutex_lock(os_mutex_t mutex){
    return xSemaphoreTake(mutex, (uint32_t)(portMAX_DELAY));
}

int32_t pal_mutex_lock_wait(os_mutex_t mutex, int32_t tick){
    return xSemaphoreTake(mutex, (uint32_t)(tick));
}

int32_t pal_mutex_unlock(os_mutex_t mutex){
    return xSemaphoreGive(mutex);
}

int gm510_sal_init(int32_t uart_port);
int32_t net_init(char_t *ip, uint32_t port){
    char_t netmode[20]={0};
    data_getstr("netmode", netmode, sizeof(netmode));
    printf("net mode:%s\r\n", netmode);
    if (strncmp(netmode, "gprs", 4) == 0){
        if (gprs_init(ip, port) != 0){
            return -1;
        }
        g_socket_api.create = pal_gprs_create_socket;
        g_socket_api.send = pal_gprs_sendall;
        g_socket_api.recv = pal_gprs_recvall;
        g_socket_api.close = pal_gprs_close_socket;
    }else if(strncmp(netmode, "line", 4) == 0){
        if (init_tcp() != 0){
            return -1;
        }
        g_socket_api.create = pal_line_create_socket;
        g_socket_api.send = pal_line_sendall;
        g_socket_api.recv = pal_line_recvall;
        g_socket_api.close = pal_line_close_socket;
    }else if (strncmp(netmode, "gm510", 4) == 0) {
        if (gm510_sal_init(3) != 0) {
            return -1;
        }
        g_socket_api.create = pal_w4g_create_socket;
        g_socket_api.send = pal_w4g_sendall;
        g_socket_api.recv = pal_w4g_recvall;
        g_socket_api.close = pal_w4g_close_socket;
        #if 0
        if (w4g_init(ip, port) != 0){
            return -1;
        }    
        g_socket_api.create = pal_w4g_create_socket;
        g_socket_api.send = pal_w4g_sendall;
        g_socket_api.recv = pal_w4g_recvall;
        g_socket_api.close = pal_w4g_close_socket;
        #endif
    }else{
        return -1;
    }
    
    
		return 0;
} 

struct SocketApi *net_get_socket_api(void){
    return &g_socket_api;
}
